package com.bee.bootstrap.system.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.bee.bootstrap.system.entity.Attachment;
import com.bee.bootstrap.system.entity.Dictionary;
import com.bee.bootstrap.system.mapper.AttachmentMapper;
import com.bee.bootstrap.system.service.IAttachmentService;
import com.bee.bootstrap.system.service.IDictionaryService;
import com.bee.bootstrap.system.service.ISequenceService;
import com.bee.bootstrap.user.entity.User;
import com.bee.bootstrap.user.service.IUserService;
import com.bee.common.core.enums.DictionaryTypeEnum;
import com.bee.common.core.enums.StatusEnum;
import com.bee.common.core.result.Result;
import com.bee.common.tools.context.SpringContextUtil;
import com.bee.common.tools.date.DateUtils;
import com.bee.common.tools.view.StringTools;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * <pre>
 *  上传路径采用系统参数配置，附件同时记录了完整的下载路径字段，
 *  需要前置web服务器配置虚拟文件目录/attachments
 *  亦可以前端自己组合路径
 * </pre>
 *
 * @author liekkas
 * @since 2018-05-08
 */
@Service
public class AttachmentServiceImpl extends ServiceImpl<AttachmentMapper, Attachment> implements IAttachmentService {

    private static Logger log = LoggerFactory.getLogger(AttachmentServiceImpl.class);

    @Autowired
    private IUserService userServiceImpl;
    @Autowired
    private ISequenceService sequenceServiceImpl;
    @Autowired
    private IAttachmentService attachmentServiceImpl;
    @Autowired
    private IDictionaryService dictionaryServiceImpl;

    private static final String TABLE_NAMME = "base_sys_attachment";
    private static final String COLUMN_NAME = "rename_file_name";
    private static final String download_uri= "attachments";

    /**
     * 获取上传的相关系统参数
     * @return
     */
    public Dictionary uploadDictionary(String key){
        //附件上传系统参数
        Dictionary uploadDictionary=dictionaryServiceImpl.selectOne(new EntityWrapper<Dictionary>()
                .eq("dictionary_key",key)
                .eq("status",StatusEnum.NORMAL.toString())
                .eq("type", DictionaryTypeEnum.System.toString()));
        return  uploadDictionary;
    }

    public Result upload(List<MultipartFile> files, String businessType,String uploadDir) throws IOException {
        String token= (String) SpringContextUtil.getRequest().getAttribute("token");
        User user=userServiceImpl.findUserByToken(token);
        //系统域名用于查看图片完整路径
        Dictionary domainDictionary=dictionaryServiceImpl.selectOne(new EntityWrapper<Dictionary>()
                .eq("dictionary_key","serverDomain")
                .eq("status",StatusEnum.NORMAL.toString())
                .eq("type", DictionaryTypeEnum.System.toString()));
        if(domainDictionary==null)
            return Result.fail("请在系统参数配置key为[serverDomain]的域名参数");
        File savePath = new File(uploadDir);
        if (!savePath.exists()) {
            savePath.mkdirs();
        }
        MultipartFile file = null;
        BufferedOutputStream stream = null;
        String rename="";
        List<Attachment> attachments=new ArrayList<Attachment>();
        for (int i = 0; i < files.size(); ++i) {
            file = files.get(i);
            if (!file.isEmpty()) {
                try {

                    Attachment attachment=new Attachment();
                    String seqStr = sequenceServiceImpl.saveSeqGenerator(TABLE_NAMME,COLUMN_NAME, null, 0);
                    rename= DateUtils.toString(new Date(), "yyyyMMddHHmmss") + seqStr;
                    attachment.setOriginalFileName(file.getOriginalFilename());
                    attachment.setRenameFileName(StringTools.renameFile(file.getOriginalFilename(),rename));
                    byte[] bytes = file.getBytes();
                    File saveFile = new File(savePath, attachment.getRenameFileName());
                    stream = new BufferedOutputStream(new FileOutputStream(saveFile));
                    stream.write(bytes);
                    stream.close();
                    //保存附件信息
                    attachment.setAttachmentSize(file.getSize());
                    attachment.setCreateTime(new Date());
                    attachment.setBusinessType(businessType);
                    attachment.setDownloadUrl(domainDictionary.getDictionaryValue()+"/"+download_uri+"/"+attachment.getRenameFileName());
                    attachment.setUserId(user!=null?user.getId():null);
                    attachment.setSort(i);
                    attachment.setStatus(StatusEnum.NORMAL.toString());
                    attachments.add(attachment);
                } catch (Exception e) {
                    log.error("第 " + i + " 个文件上传有错误" + e.getMessage());
                    return Result.fail("第 " + i + " 个文件上传有错误");
                }finally {
                    if (stream != null) {
                        stream.close();
                        stream = null;
                    }
                }
            }
        }
        if(attachments.size()>0){
            attachmentServiceImpl.insertBatch(attachments);
        }
        return Result.success("上传成功",attachments);
    }

    @Override
    public Result uploadImage(List<MultipartFile> files, String businessType) throws IOException {
        Dictionary fileDictionary=uploadDictionary("imageDir");
        if(fileDictionary==null)
            return Result.fail("请在系统参数配置key[imageDir]的图片上传路径参数");
        return this.upload(files,businessType,fileDictionary.getDictionaryValue());
    }

    @Override
    public Result uploadFiles(List<MultipartFile> files, String businessType) throws IOException {
        Dictionary fileDictionary=uploadDictionary("fileDir");
        if(fileDictionary==null)
            return Result.fail("请在系统参数配置key[fileDir]的文件上传路径参数");
        return this.upload(files,businessType,fileDictionary.getDictionaryValue());
    }

    @Override
    public Result updateCustomFileName(Long id, String customFileName) {
        Attachment attachment=this.selectById(id);
        attachment.setCustomFileName(customFileName);
        attachment.setUpdateTime(new Date());
        this.updateById(attachment);
        return Result.success("自定义名称成功");
    }

    @Override
    public Result deleteAttachment(Long id) {
        Attachment attachment=this.selectById(id);
        attachment.setStatus(StatusEnum.INVALID.toString());
        attachment.setUpdateTime(new Date());
        this.updateById(attachment);
        return Result.success("删除附件成功");
    }

    @Override
    public List<Attachment> findAttachmentsById(Collection ids) {
       return this.selectList(new EntityWrapper<Attachment>().in("id",ids));
    }

    @Override
    public List<Attachment> findAttachmentsByIds(List<Attachment> attachments, String ids) {
        List<String> idList=Arrays.asList(ids.split(","));
        List<Long> idsLong =new ArrayList<Long>(idList.size());
        CollectionUtils.collect(idList,
                new Transformer(){
                    public java.lang.Object transform(java.lang.Object input){
                        return new Long((String)input);
                    }
                } ,idsLong );
        List<Attachment> result=new ArrayList<>(idList.size());
        attachments.forEach(attachment -> {
            if(idsLong.contains(attachment.getId())){
                result.add(attachment);
            }
        });
        return  result;
    }
}
